from django.shortcuts import get_object_or_404
from rest_framework.parsers import JSONParser
from rest_framework.decorators import api_view, action
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.response import Response
from rest_framework import status

from .models import Book, Category
from .serializers import BookSerializers, CategorySerializers
from rest_framework import viewsets
from django.http import JsonResponse

from rest_framework.views import APIView

from rest_framework.generics import GenericAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins

from .permissions import IsAdminOrReadOnly
from rest_framework.authentication import SessionAuthentication, BaseAuthentication


class BookViewSets(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializers


class CategoryViewSets(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializers


@api_view(["GET", "POST"])
def book_list(req):
    if req.method == "GET":
        books = Book.objects.all()
        # many=True代表序列化的是多个内容 context={'request': req}是因为使用了HyperlinkedIdentityField
        seria = BookSerializers(instance=books, many=True, context={'request': req})
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "获取列表",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "获取列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "POST":
        # data = JSONParser().parse(req)
        data = req.data
        seria = BookSerializers(data=data, context={'request': req})
        # print(seria.data)
        seria.is_valid(raise_exception=True)
        seria.save()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "创建书籍",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "创建书籍",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


@api_view(["GET", "PUT", "DELETE"])
def book_detail(req, pk):
    book = get_object_or_404(Book, pk=pk)
    if req.method == "GET":
        seria = BookSerializers(book, context={'request': req})
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "获取书籍详情",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "获取书籍详情",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "PUT":
        # data = JSONParser().parse(req)
        data = req.data
        seria = BookSerializers(instance=book, data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "修改信息",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "修改信息",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "DELETE":
        book.delete()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "修改信息",
        # })
        return Response(data={
            "code": 0,
            "msg": "修改信息",
        }, status=status.HTTP_204_NO_CONTENT)


@api_view(["GET", "POST"])
def category_list(req):
    if req.method == "GET":
        categorys = Category.objects.all()
        seria = CategorySerializers(categorys, many=True, context={'request': req})
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "获取分类列表",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "获取分类列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "POST":
        # data = JSONParser().parse(req)
        data = req.data
        seria = CategorySerializers(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "添加分类",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "添加分类",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


@api_view(["GET", "PUT", "DELETE"])
def category_detail(req, pk):
    category = get_object_or_404(Category, pk=pk)
    if req.method == "GET":
        seria = CategorySerializers(category, context={'request': req})
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "获取分类详情",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "获取分类详情",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "PUT":
        # data = JSONParser().parse(req)
        data = req.data
        seria = CategorySerializers(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "修改分类",
        #     "data": seria.data
        # })
        return Response(data={
            "code": 0,
            "msg": "修改分类",
            "data": seria.data
        }, status=status.HTTP_200_OK)
    elif req.method == "DELETE":
        category.delete()
        # return JsonResponse({
        #     "code": 0,
        #     "msg": "删除分类",
        # })
        return Response(data={
            "code": 0,
            "msg": "删除分类",
        }, status=status.HTTP_204_NO_CONTENT)


class BookListView(APIView):
    def get(self, req):
        books = Book.objects.all()
        seria = BookSerializers(instance=books, many=True, context={'request': req})
        return Response(data={
            "code": 0,
            "msg": "获取列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)

    def post(self, req):
        data = req.data
        seria = BookSerializers(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        return Response(data={
            "code": 0,
            "msg": "创建书籍",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


class BookDetailView(APIView):
    def get(self, req, pk):
        try:
            book = Book.objects.get(pk=pk)
            seria = BookSerializers(book, context={'request': req})
            return Response(data={
                "code": 0,
                "msg": "获取书籍详情",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def put(self, req, pk):
        try:
            book = Book.objects.get(pk=pk)
            data = req.data
            seria = BookSerializers(instance=book, data=data, context={'request': req})
            seria.is_valid(raise_exception=True)
            seria.save()
            return Response(data={
                "code": 0,
                "msg": "修改信息",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, req, pk):
        try:
            book = Book.objects.get(pk=pk)
            book.delete()
            return Response(data={
                "code": 0,
                "msg": "修改信息",
            }, status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CategoryListView(APIView):
    def get(self, req):
        categorys = Category.objects.all()
        seria = CategorySerializers(instance=categorys, many=True, context={'request': req})
        return Response(data={
            "code": 0,
            "msg": "获取列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)

    def post(self, req):
        data = req.data
        seria = CategorySerializers(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        return Response(data={
            "code": 0,
            "msg": "创建分类",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


class CategoryDetailView(APIView):
    def get(self, req, pk):
        try:
            category = Category.objects.get(pk=pk)
            seria = CategorySerializers(category, context={'request': req})
            return Response(data={
                "code": 0,
                "msg": "获取分类详情",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def put(self, req, pk):
        try:
            category = Category.objects.get(pk=pk)
            data = req.data
            seria = CategorySerializers(instance=category, data=data, context={'request': req})
            seria.is_valid(raise_exception=True)
            seria.save()
            return Response(data={
                "code": 0,
                "msg": "修改分类",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, req, pk):
        try:
            category = Category.objects.get(pk=pk)
            category.delete()
            return Response(data={
                "code": 0,
                "msg": "删除分类",
            }, status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class BookListGenericView(GenericAPIView):
    """
    通用api视图：代码重复率高
    """

    def get_queryset(self):
        return Book.objects.all()

    def get_serializer_class(self):
        return BookSerializers

    def get(self, req):
        seria = self.get_serializer(instance=self.get_queryset(), many=True, context={'request': req})
        return Response(data={
            "code": 0,
            "msg": "获取列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)

    def post(self, req):
        data = req.data
        seria = self.get_serializer(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        return Response(data={
            "code": 0,
            "msg": "创建书籍",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


class BookDetailGenericView(GenericAPIView):
    """
    通用api视图：代码重复率高
    """

    def get_queryset(self):
        return Book.objects.all()

    def get_serializer_class(self):
        return BookSerializers

    def get(self, req, pk):
        try:
            object = self.get_object()
            seria = BookSerializers(object, context={'request': req})
            return Response(data={
                "code": 0,
                "msg": "获取书籍详情",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def put(self, req, pk):
        try:
            object = self.get_object()
            data = req.data
            seria = BookSerializers(instance=object, data=data, context={'request': req})
            seria.is_valid(raise_exception=True)
            seria.save()
            return Response(data={
                "code": 0,
                "msg": "修改信息",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, req, pk):
        try:
            object = self.get_object()
            object.delete()
            return Response(data={
                "code": 0,
                "msg": "修改信息",
            }, status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CategoryListGenericView(GenericAPIView):
    """
    通用api视图：代码重复率高
    """

    def get_queryset(self):
        return Category.objects.all()

    def get_serializer_class(self):
        return CategorySerializers

    def get(self, req):
        seria = self.get_serializer(instance=self.get_queryset(), many=True, context={'request': req})
        return Response(data={
            "code": 0,
            "msg": "获取列表",
            "data": seria.data
        }, status=status.HTTP_200_OK)

    def post(self, req):
        data = req.data
        seria = self.get_serializer(data=data, context={'request': req})
        seria.is_valid(raise_exception=True)
        seria.save()
        return Response(data={
            "code": 0,
            "msg": "创建分类",
            "data": seria.data
        }, status=status.HTTP_201_CREATED)


class CategoryDetailGenericView(GenericAPIView):
    """
    通用api视图：代码重复率高
    """
    lookup_field = "pk"

    def get_queryset(self):
        return Category.objects.all()

    def get_serializer_class(self):
        return CategorySerializers

    def get(self, req, pk):
        try:
            object = self.get_object()
            seria = self.get_serializer(object, context={'request': req})
            return Response(data={
                "code": 0,
                "msg": "获取分类详情",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def put(self, req, pk):
        try:
            object = self.get_object()
            data = req.data
            seria = self.get_serializer(instance=object, data=data, context={'request': req})
            seria.is_valid(raise_exception=True)
            seria.save()
            return Response(data={
                "code": 0,
                "msg": "修改分类",
                "data": seria.data
            }, status=status.HTTP_200_OK)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, req, pk):
        try:
            object = self.get_object()
            object.delete()
            return Response(data={
                "code": 0,
                "msg": "删除分类",
            }, status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class BookListCreateGenericView(ListCreateAPIView):
    """
    book列表视图：浓缩
    """

    def get_queryset(self):
        return Book.objects.all()

    def get_serializer_class(self):
        return BookSerializers


class BookDetailRetrieveUpdateDestroyGenericView(RetrieveUpdateDestroyAPIView):
    """
    book详情视图：浓缩
    """

    def get_queryset(self):
        return Book.objects.all()

    def get_serializer_class(self):
        return BookSerializers


class CategoryListCreateGenericView(ListCreateAPIView):
    """
    分类列表视图：浓缩
    """

    def get_queryset(self):
        return Category.objects.all()

    def get_serializer_class(self):
        return CategorySerializers


class CategoryDetailRetrieveUpdateDestroyGenericView(RetrieveUpdateDestroyAPIView):
    """
    分类详情视图：浓缩
    """
    lookup_field = "pk"

    def get_queryset(self):
        return Category.objects.all()

    def get_serializer_class(self):
        return CategorySerializers


class BookGenericViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.RetrieveModelMixin,
                         mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericViewSet):
    """
    book视图集：精简
    """

    lookup_field = "pk"

    @action(["GET"], detail=False)
    def books_top3(self, req):
        top3 = self.get_queryset().order_by("-pub_date")[:3]
        seria = self.get_serializer(top3, many=True)
        return Response(data=seria.data, status=status.HTTP_200_OK)

    def get_queryset(self):
        return Book.objects.all()

    def get_serializer_class(self):
        return BookSerializers


class CategoryGenericViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.RetrieveModelMixin,
                             mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericViewSet):
    """
    分类视图集：精简
    """
    lookup_field = "pk"
    # 优先级高于django.settings配置 高于rest_framework.settings配置
    # authentication_classes = [SessionAuthentication]
    permission_classes = [IsAdminOrReadOnly]  # 权限配置

    def get_queryset(self):
        return Category.objects.all()

    def get_serializer_class(self):
        return CategorySerializers
